using System;
using System.Collections.Generic;
using OpenViewer.Render;
using OpenViewer.UI;
using ThirdLife.UI.WinForms.Modules;

namespace ThirdLife.UI.WinForms
{
  public class ThirdLifeUIPlugin : UIBase
  {
    private readonly Dictionary<string, IUIModule> _uiModules;

    public ThirdLifeUIPlugin()
    {
      _uiModules = new Dictionary<string, IUIModule>();
    }

    public override string GetName()
    {
      return "ThirdLife";
    }

    public override void Initialize(string renderingEngine, string loginURI, string username, string password)
    {
      base.Initialize(renderingEngine, loginURI, username, password);

      UIModuleServices.Instance.Metaverse.DefaultName = username;
      UIModuleServices.Instance.Metaverse.DefaultPassword = password;
      UIModuleServices.Instance.Metaverse.DefaultURL = loginURI;
      UIModuleServices.Instance.Metaverse.RenderingEngineGenerator = new RenderingEngineFactory( delegate(IntPtr handle)
                                                                                                  {
                                                                                                    RenderingEngineManager renderingEngineManager = new RenderingEngineManager();
                                                                                                    m_renderingEngine = renderingEngineManager.GetEngine(renderingEngine);
                                                                                                    m_renderingEngine.Initialize(m_model, handle, 800, 600);
                                                                                                    return m_renderingEngine;
                                                                                                  });
      UIModuleServices.Instance.Metaverse.DisconnectFromGrid += new GenericEventHandler(Metaverse_DisconnectFromGrid);
      UIModuleServices.Instance.Communication.ChatSent += new ChatSentHandler(Communication_ChatSent);
     
      m_model.OnConnected += new OpenViewer.Models.Connected(m_model_OnConnected);
      m_model.OnChat += new OpenViewer.Protocol.Chat(m_model_OnChat);
      UIModuleServices.Instance.Metaverse.ConnectToGrid += new ConnectToGridHandler(Metaverse_ConnectToGrid);
    }

    void m_model_OnChat(string message, string fromName, OpenViewer.Protocol.ChatType type, Guid id, Guid ownerid, Math3D.Vector3 position)
    {
      UIModuleServices.Instance.Communication.RecievedChat(fromName,message);
    }

    void Metaverse_DisconnectFromGrid()
    {
      m_model.Logout();
    }

    void Communication_ChatSent(string message)
    {
      UIModuleServices.Instance.Communication.SelfChat("REPLACE WITH AVATAR NAME", message);
      m_model.Say(message);
    }

    private class RenderingEngineFactory : IRenderingEngineFactory
    {
      private GenerateRenderingEngine _engineGenerator;

      public RenderingEngineFactory(GenerateRenderingEngine engineGenerator)
      {
        _engineGenerator = engineGenerator;  
      }

      public IRenderingEngine Generate()
      {
        return _engineGenerator(IntPtr.Zero);
      }

      public IRenderingEngine Generate(IntPtr handle)
      {
        return _engineGenerator(handle);
      }
    }

    void m_model_OnConnected()
    {
      UIModuleServices.Instance.Metaverse.NotifyMetaverseConnectivity();
      UIModuleServices.Instance.Metaverse.NotifyReadyForRendering();
      
    }

    void Metaverse_ConnectToGrid(string name, string password, string url)
    {
      m_model.BeginLogin(url, name, password);
    }

    private void StartThirdLife()
    {
      UIModuleServices.Instance.Startup.StartupApplication();
    }

    private void LoadUIModules()
    {
      List<IUIModule> modules = new List<IUIModule>();

      //for right now, order of these things matters pretty significantly, I need to think of how to call events better before Application.Start
      modules.Add(new SimpleMetaverseConnectionUIModule());
      modules.Add(new AboutBoxUIModule());
      modules.Add(new MenuBarUIModule());
      modules.Add(new AddressBarUIModule());
      modules.Add(new ChatAreaUIModule());
      modules.Add(new Canvas3D());
      modules.Add(new MainScreenUIModule());

      foreach (IUIModule module in modules)
      {
        module.ModuleServices = UIModuleServices.Instance;
        module.Setup();
        _uiModules.Add(module.Name, module);
      }
    }

    public override void Run()
    {
      LoadUIModules();
      StartThirdLife();
    }
  }
}
